﻿<!-- 更新于2024-10-28 office类型只加载一次问题修复 -->
<!-- 更新于2024-10-23 列额外数据加载逻辑优化 -->
<!-- 更新于2024-10-22 部分情况下文本不对齐问题优化 -->
<!-- 更新于2024-10-21 加载数据单位数据优化，解决修改数据后显示异常及编辑异常问题 -->
<!-- 更新于2024-09-05 office类型字段数据加载接口变更，user类型字段数据加载接口变更，加载逻辑优化 -->
<!-- 更新于2023-12-28 -->
<style>
.record-table.el-table th {
  background-color: rgb(245, 247, 250);
}
.record-table.el-table tr {
  /*line-height: 34px;*/
  height: 34px;
}
.record-table .el-table__body tr,
.record-table .el-table__body td {
  padding: 0;
}

.record-table .el-table__body td .cell,.record-table .el-table__body td .cell:first {
    padding: 0;
  }

.record-table .el-table__body td .cell .el-input__inner {
  border: 1px solid hsla(0, 0%, 100%, 0) !important;
  border-radius: 0 !important;
  padding: 0 0 0 5px !important;
  background-color: transparent;
  height: 30px;
}

.record-table.el-table th>.cell {
  padding-left: 5px;
  padding-right: 5px;
}
.readonly .record-table .el-table__body td .cell {
  /*padding-left: 5px;*/
  /*padding-right: 5px;*/
  padding: 2px 5px 2px 5px;
}

.record-table.el-table .cell-selected {
  background-color: #9ed0ff !important;
}
.record-table.el-table .cell-changed {
  background-color: #fdf6ec !important;
}

.el-tabs--border-card>.el-tabs__content {
  padding: 5px;
}


.record-table .el-input-group__append,
.el-input-group__prepend {
  padding: 0 10px;
}

.record-table .el-input__inner {
  padding: 0 8px;
}
.record-table .el-tag {
  height: auto;
  line-height: normal;
  padding: 3px 7px 3px 7px;
}
/*解决复选框禁用后外侧阴影问题*/
.record-table .el-table__row .cell .el-checkbox.is-disabled {
  background-color: transparent;
}
.record-table .el-select .el-input__icon {
  line-height: 100%;
}
</style>
<template>
  <div style="position: relative;box-sizing: border-box;" v-loading="isLoading"
       :element-loading-text="loadingText" :class="readonly?'readonly':''">
    <el-table v-if="dataList" :id="tableId" :key="'record-table'+timestamp" :ref="'record-table'+timestamp" class="record-table" :data="dataList" :fit="fit"
              border highlight-current-row :max-height="maxHeight"
              :show-summary="showSummary"
              :row-style="rowStyle"
              @selection-change="handleSelectChange"
              :header-cell-style="headerCellStyleRender" :cell-style="(val)=>{return cellStyleRender(val,cellStyle)}" :style="tableStyle"
              @cell-mouse-enter="(row, column, cell, event)=>handleMouseMove(event,column.property,row)"
              @mouseup.native="handleMouseUp($event)"
              :span-method="(val) => {return excelMergeMethod(val)}"
              @virtual-change="updateVirtualDataRange($event)"
              @mouseleave.native="handleLeaveTable" @copy.native="handleCopy" empty-text="暂无数据">
      <el-table-column v-if="showCheckbox" :key="timestamp+'_checkbox'" type="selection" width="25" :selectable="selectable" align="center" fixed="left"></el-table-column>
      <el-table-column v-if="showIndex" :key="timestamp+'_index'" width="55" label="序号" align="center" fixed="left">
        <template slot-scope="scope">
          {{scope.row.rowNum+1}}
        </template>
      </el-table-column>

      <el-table-column-extend v-for="field in columnList" :field="field" @handleEscClick="handleEscClick"
                              @handleDeleteClick="handleDeleteClick"
                              :select-area="selectArea"
                              :change-cell-map="changeCellMap"
                              :cell-change="handleCellChange"
                              :key="'record-table_column'+timestamp+field.id"
                              @handleEnterClick="handleEnterClick" @handleMouseUp="handleMouseUp" @handleMouseDown="handleMouseDown"
                              @handlePaste="handlePaste" :columnWidthMap="columnWidthMap"
                              :fieldDataNameMap="fieldDataNameMap"
                              :fieldDataListMap="fieldDataListMap"
                              :cell-readonly="cellReadonly"
                              :readonly="readonly">
      </el-table-column-extend>
    </el-table>

  </div>

</template>

<script>
export default {
  name: "RecordTable",
  props: {
    maxHeight: {
      type: Number,
      default: 800
    },
    // //锁定行数
    // frozenRow:{
    //   type: Number,
    //   default:0
    // },
    data: {
      type: Array,
      default:()=>{return [];}
    },
    /**
     * 是否展示合计行
     */
    showSummary:{
      type:Boolean,
      default:false
    },
    /*
    * 列定义信息
    * type:列类型,meta:元数据，office:组织机构，user:用户id，button:按钮
    * id:列id，不可重复
    * name:列名称
    * width:列宽，数字
    * align:对齐方式
    * permission 所需权限
    *
    * */
    columns: {
      type: Array,
    },
    fit:{
      type:Boolean,
      default:true,
    },
    //单元格样式
    cellStyle: {
      type: Function,
      default: () => {
      }
    },
    //边框颜色
    borderColor:{
      type:String,
      default:''
    },
    readonlyColor:{
      type:String,
      default:''
    },
    //是否只读
    readonly:{
      type:Boolean,
      default:false,
    },
    //单元格是否只读,函数，第一参数为行数据，第二参数为列信息
    cellReadonly:{
      type:Function,
      default:null,
    },
    // 合计列合计方法
    summaryMethod:{
      type:Function,
      default:null,
    },
    //是否显示选择框,左侧复选框
    selectable:{
      type:Function,
      default:()=>{return true;}
    },
    //是否显示行号
    showIndex:{
      type:Boolean,
      default:false
    },
    //是否显示行号
    showCheckbox:{
      type:Boolean,
      default:false
    },
    //默认选中项
    defaultSelected:{
      type:Function,
      default:null
    },
    //行样式
    rowStyle:{
      type:Object,
      default:null
    },
    id:{
      type:String,
      default:'record-table-'+new Date().getTime()
    }
  },
  data() {
    return {
      isLoading: false,
      loadingText: '正在处理...',
      formLabelWidth: '120px',
      //表格id，如果以数字开头会出问题，所以加前缀处理
      tableId:'tid-'+this.id,
      //记录字段id-name映射关系
      fieldDataNameMap:{
        'unit-type':{}
      },
      //记录字段数据列表
      fieldDataListMap:{
      },
      //字段数据初始化记录
      fieldDataInitMap:{
      },
      //录入数据
      recordData: null,
      //选中区域
      selectArea: {
        cellMap: null
      },
      //填充配置
      fillOption:{
        beginRow:null,
        beginField:null
      },
      virtualMode:false,//是否启用虚拟视图
      virtualDataRange:null,//虚拟视图下显示数据范围
      updateAreaTask: null,
      //计算后的列宽集合
      columnWidthMap: {},
      //数据列表
      dataList:null,
      //表格整体样式
      tableStyle:{},
      //合并区域
      mergeRange:{},
      //列信息
      columnList:[],
      //叶子节点列信息,只包含最底层列，忽略合并列
      leafColumnList:[],
      columnMap: {},
      //名称展示映射
      nameDisplayMap: {},
      //时间戳
      timestamp:new Date().getTime(),
      //用户信息缓存数据
      userMap:{},
      //组织机构信息缓存数据
      officeMap:{},
      //数据更改后的单元格
      changeCellMap:{
      }
    }
  },

  watch: {
    data: {
      handler(val, oldVal) {
        this.init();
      },
      // deep: true
    },
    columns: {
      handler(val, oldVal) {
        this.init();
      },
      dataList: {
        handler(val, oldVal) {
          if(this.readonly) {
            //如果是只读的，数据变更后组织机构和用户重新加载
            this.fieldDataInitMap['loading-office'] = null;
            this.fieldDataInitMap['loading-user'] = null;
            this.loadFieldExtraData(this.leafColumnList, this.dataList);
          }
          this.$emit("change",this.dataList);
        },
        deep: true
      },
      deep: true
    },
  },

  created: function () {
    this.init();
  },
  mounted: function () {

  },

  methods: {
    //初始化
    init() {
      this.changeCellMap = {};
      if(!this.columns) {
        return;
      }
      if (this.borderColor) {
        this.tableStyle['border-color'] = this.borderColor;
      }
      if (!this.data) {
        return;
      }
      let rowIndex = 0;
      for (let item of this.data) {
        item.rowNum = rowIndex++;
      }

      let columnList = [];
      let leafColumnList = [];
      for (let sourceCol of this.columns) {
        let col = JSON.parse(JSON.stringify(sourceCol));
        if(sourceCol.isHide&&sourceCol.isHide()) {
          //如果是隐藏列，则不展示
        } else {
          columnList.push(col);
        }
        this.initColumn(sourceCol,col,leafColumnList);

        if(col.type=='button') {
          if(sourceCol.children) {
            //由于复制无法复制函数，需要使用原有数据
            let btnList = [];
            for(let btn of sourceCol.children) {
              //检查按钮权限
              if(!btn.permission||this.checkPermission(btn.permission)) {
                btnList.push(btn);
              }
            }
            col.children = btnList;
          }
          if(sourceCol.header&&sourceCol.header.children) {
            //由于复制无法复制函数，需要使用原有数据
            let btnList = [];
            for(let btn of sourceCol.header.children) {
              //检查按钮权限
              if(!btn.permission||this.checkPermission(btn.permission)) {
                btnList.push(btn);
              }
            }
            col.header.children = btnList;
          }
        }


        if (this.data) {
          //初始化数据
          for (let row of this.data) {
            if (!row[col.id]&&parseInt(row[col.id])!=0&&row[col.id]!==false) {
              //注意处理0要显示
              // row[col.id] = '';左侧写法会造成这些属性无法监听，应用下方写法
              this.$set(row,col.id,'');
            }
          }
        }
      }
      //加载字段选择数据、展示数据等
      this.loadFieldExtraData(leafColumnList,this.data);
      this.columnList = columnList;
      this.leafColumnList = leafColumnList;
      let list = [];
      for (let item of this.data) {
        list.push(item);
      }
      this.dataList = list;
      if (!list) {
        return;
      }

      let mergeRange = {};
      let cellMergeList = [];
      //支持纵向相同数据单元格合并
      let leftPath = [];
      for (let colIndex = 0; colIndex < this.leafColumnList.length; colIndex++) {
        let col = this.leafColumnList[colIndex];

        if (!col.verticalMerge) {
          continue;
        }
        if (col.id) {
          leftPath.push(col.id);
        }
        let preMerge = null;
        for (let rowIndex = 0; rowIndex < list.length; rowIndex++) {
          let row = list[rowIndex];
          let compareValue = '';
          for (let colId of leftPath) {
            compareValue += row[colId] + ":";
          }
          if (preMerge) {
            if (preMerge.compareValue == compareValue) {
              //如果当前行对比数据与上一单元格相同，则更新合并区域下限
              preMerge.lastRow = rowIndex;
              if (rowIndex == list.length - 1) {
                //如果当前行为最后一行，则将区域新增至合并区域列表
                cellMergeList.push(preMerge);
              }
            } else {
              cellMergeList.push(preMerge);
              preMerge = null;
            }
          }
          if (!preMerge) {
            preMerge = {};
            preMerge.firstRow = rowIndex;
            preMerge.lastRow = rowIndex;
            preMerge.firstColumn = colIndex;
            preMerge.lastColumn = colIndex;
            preMerge.compareValue = compareValue;
          }
        }
      }
      // //此处加一个合并区域，用来处理表头右侧填充滚动条空缺
      // cellMergeList.push({
      //   firstRow: 0,
      //   lastRow: this.frozenRow - 1,
      //   firstColumn: this.columnList.length,
      //   lastColumn: this.columnList.length
      // })
      //记录单元格是否在合并区域内
      let mergeCellMap = {};

      // //右侧固定列特殊处理，合并表头
      // if (this.rightFixColumns && this.rightFixColumns.length > 0 && this.frozenRow > 0) {
      //   for (let i = 0; i < this.rightFixColumns.length; i++) {
      //     cellMergeList.push({
      //       firstRow: 0,
      //       lastRow: this.frozenRow - 1,
      //       firstColumn: this.columnList.length + i,
      //       lastColumn: this.columnList.length + i
      //     });
      //   }
      //
      // }
      // //最后一列为占位符，宽度等于下方滚动条宽度
      // let offset = this.rightFixColumns ? this.rightFixColumns.length : 0;
      // cellMergeList.push({
      //   firstRow: 0,
      //   lastRow: this.frozenRow - 1,
      //   firstColumn: this.columnList.length + offset,
      //   lastColumn: this.columnList.length + offset
      // });
      for (let item of cellMergeList) {
        for (let i = item.firstRow; i <= item.lastRow; i++) {
          let rowspan = 0;
          if (i == item.firstRow) {
            rowspan = item.lastRow - item.firstRow + 1;
          }
          let horizontalMerge = item.lastColumn - item.firstColumn > 0;
          for (let j = item.firstColumn; j <= item.lastColumn; j++) {
            if (horizontalMerge) {
              mergeCellMap[i + ',col' + j] = true;
            }
            let colspan = 0;
            if (j == item.firstColumn) {
              colspan = item.lastColumn - item.firstColumn + 1;
            }
            mergeRange[i + '_' + j] = {
              rowspan: rowspan,
              colspan: colspan,
              align: item.align
            };
          }
        }
      }
      this.mergeRange = mergeRange;

      // for (let col of this.columnList) {
      //   let widthResult = this.judgeAvgColumnWidth(sheet, col, sheet.dataList, mergeCellMap)
      //   this.columnWidthMap[sheet.name + '$' + col] = widthResult;
      // }
      // let dataList = [];
      // if (this.frozenRow >= list.length) {
      //   this.frozenRow = 0;
      // }
      // for (let i = 0; i < this.frozenRow; i++) {
      //   dataList.push(list[i]);
      // }
      // //将主数据去除锁定行数据
      // let bodyDataList = [];
      // for (let i = 0; i < list.length; i++) {
      //   let rowData = list[i];
      //   rowData.rowNum = i;
      // if (i < this.frozenRow) {
      //   continue;
      // }
      // bodyDataList.push(rowData);
      // rowData.virtualRowNum = i - this.frozenRow;
      // if(this.rightFixColumns) {
      //   for (let item of this.rightFixColumns) {
      //     if (!item.id || !item.formatter) {
      //       continue;
      //     }
      //     rowData[item.id] = item.formatter(rowData);
      //   }
      // }
      // }
      // this.bodyDataList = bodyDataList;
      // if (list.length * 28 > this.maxHeight * 2 && list.length > 30) {
      //   //如果数据过多，则开启该标签页虚拟视图
      //   this.virtualMode = true;
      // }
      // this.frozenDataList = dataList;

      this.$nextTick(()=>{
        if(this.showCheckbox&&this.defaultSelected) {
          //如果显示复选框，则对默认选中项进行选中操作
          for(let item of this.dataList) {
            if(this.defaultSelected(item)) {
              let table = this.$refs['record-table' + this.timestamp];
              if(table) {
                table.toggleRowSelection(item, true);
              } else {
                console.error('无法找到对应多选表格');
              }

            }
          }
        }
      })
    },
    //初始化列宽
    initColumn(sourceCol,col,leafColumnList) {
      this.columnMap[col.id]=col;

      if(col.children&&col.children.length>0&&sourceCol.children) {
        for(let i=0;i<col.children.length;i++) {
          if(i>=sourceCol.children.length) {
            continue;
          }
          this.initColumn(sourceCol.children[i],col.children[i],leafColumnList);
        }
      } else {
        leafColumnList.push(col);
      }
      //初始化宽度数据
      if (col.width && col.width > 0) {
        this.columnWidthMap[col.id] = col.width;
      } else if (!this.fit) {
        let widthResult = this.judgeLongestColumnWidth(col, this.data)
        this.columnWidthMap[col.id] = widthResult;
      }

      if(col.showOverflowTooltip == undefined&&(this.readonly||col.readonly)) {
        //默认超长单行显示并提示
        col.showOverflowTooltip=true;
      }

      if(sourceCol.formatter) {
        //函数无法复制，需要特殊处理
        col.formatter = sourceCol.formatter;
      }
      if(sourceCol.change) {
        //函数无法复制，需要特殊处理
        col.change = sourceCol.change;
      }
      //将组件统一转换为对象
      if(typeof sourceCol.component == 'string'){
        col.component = {id:sourceCol.component};
      } else if(!sourceCol.component) {
        col.component = {};
      }
      if(sourceCol.component&&sourceCol.component.getType) {
        //绑定函数
        col.component.getType = sourceCol.component.getType;
      }
    },


    save() {
      //回调父级方法
      this.$emit('save-data', '');
    },

    //处理粘贴事件
    handlePaste: function (event, fieldId, row) {
      if (!this.dataList || this.dataList.length <= 0) {
        return;
      }
      //处理来自excel的粘贴数据
      let text = event.clipboardData.getData('text');
      if (!text || text == '') {
        return;
      }
      let rows = text.split('\n');
      let pasteRows = [];
      for (let i = 0; i < rows.length; i++) {
        if(i == rows.length -1 && rows[i]=='') {
          continue;
        }
        let cols = rows[i].split("\t");
        pasteRows.push(cols);
      }
      if (pasteRows.length <= 0) {
        return;
      }
      let startRowNum = row.rowNum;
      let lastRowNum = this.dataList[this.dataList.length - 1].rowNum;

      let rowMap = {};
      for (let item of this.dataList) {
        rowMap[item.rowNum + ''] = item;
      }
      for (let j = 0; j < this.leafColumnList.length; j++) {
        //先对列进行循环，找到开始列
        let field = this.leafColumnList[j];
        if (field.id == fieldId) {
          for (let k = 0; k < pasteRows.length; k++) {
            if (k + startRowNum > lastRowNum) {
              break;
            }
            for (let l = 0; l < pasteRows[k].length; l++) {
              if (j + l >= this.leafColumnList.length) {
                break;
              }
              let targetField = this.leafColumnList[j + l];
              let val = pasteRows[k][l].trim();
              if (targetField.dataType && targetField.dataType == 'number') {
                val = val.replace(/[^\d.]/g, '');
              }
              rowMap[k + startRowNum + ''][targetField.id] = val;
              this.changeCellMap[targetField.id+':'+(k+startRowNum)] = true;
            }
          }
          break;
        }
      }
      this.$emit('paste',pasteRows,fieldId);
    },
    //处理复制事件
    handleCopy: function (event) {
      if (!this.selectArea||!this.selectArea.cellMap) {
        return;
      }
      //处理来自excel的粘贴数据
      // let text = event.clipboardData.getData('text');
      let data = '';
      let dataMap = {};
      for (let item of this.dataList) {
        dataMap[item.rowNum + ''] = item;
      }
      let beginRow = this.selectArea.beginRow;
      let endRow = this.selectArea.endRow;
      if(beginRow>endRow) {
        //如果拖动方向为自下往上，则会出现此情况
        let tmp = beginRow;
        beginRow = endRow;
        endRow = tmp;
      }
      let beginCol = 0,endCol = 0;
      for (let i=0;i<this.leafColumnList.length;i++) {
        let field = this.leafColumnList[i];
        if(field.id==this.selectArea.beginField) {
          beginCol = i;
        }
        if(field.id==this.selectArea.endField) {
          endCol = i;
        }
      }
      if(beginCol>endCol){
        //如果是自右向左选择，则会出现该情况
        let tmp = beginCol;
        beginCol = endCol;
        endCol = tmp;
      }
      for (let i = beginRow; i <= endRow; i++) {
        let line = '';
        for (let j=beginCol;j<=endCol;j++) {
          let field = this.leafColumnList[j];
          let value = dataMap[i + ''][field.id];
          if(value!==false&&value!=0&&!value) {
            value = ' ';
          }
          line += value;
          if(j!=endCol) {
            line += '\t';
          }
        }
        data += line;
        if (i == endRow) {
          break;
        }
        data += '\n';
      }
      this.$copyText(data).then(function (e) {
        console.log("内容已复制")
        // console.log(e)
      }, function (e) {
        alert('无法复制')
        console.log(e)
      })

    },
    handleMouseDown: function (event, fieldId, row) {
      this.fillOption = {
        beginRow:row.rowNum,
        beginField:fieldId
      }
      if (this.selectArea && this.selectArea.selecting){
        this.selectArea.selecting = false;
        return true;
      }
      if (this.selectArea && !this.selectArea.selecting && event.shiftKey) {
        this.selectArea.selecting = true;
        return true;
      }
      this.selectArea = {
        beginRow: row.rowNum,
        beginField: fieldId,
        cellMap: null,
        selecting: true,
      };
      return true;
    },
    handleMouseMove: function (event, fieldId, row) {
      if (!this.selectArea) {
        return;
      }
      if (!this.selectArea.selecting) {
        //未选择起始格/选择已结束，忽略
        return;
      }
      if (this.selectArea.currentField == fieldId && this.selectArea.currentRow == row.rowNum) {
        //本次位置与上次相同，不做处理
        return;
      }
      this.selectArea.currentField = fieldId;
      this.selectArea.currentRow = row.rowNum;
      if (this.updateAreaTask != null) {
        clearTimeout(this.updateAreaTask);
      }
      this.updateAreaTask = setTimeout(() => {
        let area = this.caculateSelectArea(this.selectArea.beginField, this.selectArea.beginRow, fieldId, row
            .rowNum);
        this.selectArea.cellMap = area.cellMap;
        this.updateAreaTask = null;
      }, 10)


    },
    handleEscClick: function (event, fieldId, row) {
      this.selectArea = {};
    },
    //监听删除按钮按下，批量删除选中区域数据
    handleDeleteClick: function (event, columnId, row) {
      if(this.readonly) {
        //如果表格为只读，则不做处理
        return;
      }
      if (!this.selectArea || !this.selectArea.cellMap) {
        return;
      }
      //将数据转换为行为key，数据为value的map集合，后续使用
      let rowMap = {};
      for (let item of this.dataList) {
        rowMap[item.rowNum + ''] = item;
      }

      for (let key in this.selectArea.cellMap) {
        if (!key) {
          continue;
        }
        //获取行列信息
        let tmpArray = key.split("\:");

        if (!tmpArray || tmpArray.length < 2) {
          continue;
        }
        //获取列id
        let fieldId = tmpArray[0];
        let fieldInfo = this.columnMap[fieldId];
        if(fieldInfo&&fieldInfo.readonly) {
          //如果当前字段为只读，则不作处理
          continue;
        }
        let targetRow = rowMap[tmpArray[1] + ''];
        if (targetRow) {
          if(fieldInfo&&this.cellReadonly&&this.cellReadonly(targetRow,fieldInfo)) {
            //如果当前单元格为只读，则不做处理
            continue;
          }
          targetRow[fieldId] = '';
        }
      }
      this.selectArea = {};
    },
    //监听回车按钮按下，输入框焦点下移
    handleEnterClick: function (event, fieldId, row) {
      let input = document.getElementById('input:' + fieldId + ':' + (row.rowNum + 1));
      if (input) {
        input.focus()
      }

    },
    handleLeaveTable: function (event) {
      if (!this.selectArea) {
        return;
      }
      this.selectArea.selecting = false;
    },
    //处理鼠标按键抬起事件
    handleMouseUp: function (event, fieldId, row) {
      if (!this.selectArea) {
        return;
      }
      this.selectArea.selecting = false;

      if (this.updateAreaTask != null) {
        clearTimeout(this.updateAreaTask);
      }
      // let area = this.caculateSelectArea(this.selectArea.beginField, this.selectArea.beginRow, fieldId, row.rowNum);
      let area = this.caculateSelectArea(this.selectArea.beginField, this.selectArea.beginRow, this.selectArea.currentField, this.selectArea.currentRow);
      if(area.beginRow==area.endRow&&area.beginField==area.endField) {
        //如果只有一个选中单元格，则认为不是选择状态
        this.selectArea = null;
        return true;
      }
      this.selectArea.beginRow = area.beginRow;
      this.selectArea.endRow = area.endRow;
      this.selectArea.beginField = area.beginField;
      this.selectArea.endField = area.endField;
      this.selectArea.cellMap = area.cellMap;
      return true;
    },
    //计算选择区域
    caculateSelectArea: function (field1, rowNum1, field2, rowNum2) {

      //需要考虑选取方向，可能左上至右下，右上至左下，右下至左上，左下至右上
      //超出选择界限
      let selectFieldArray = [];
      let fieldBound = {
        begin: null,
        end: null
      };
      if (field1 == field2||(field1&&!field2)) {
        fieldBound.begin = field1;
        fieldBound.end = field1;
      } else {
        for (let field of this.leafColumnList) {
          if (field.id != field1 && field.id != field2) {
            continue;
          }
          if (!fieldBound.begin) {
            fieldBound.begin = field.id;
          } else {
            fieldBound.end = field.id;
          }
        }
      }
      for (let field of this.leafColumnList) {
        if (selectFieldArray.length <= 0 && field.id != fieldBound.begin) {
          continue;
        }
        selectFieldArray.push(field);
        if (field.id == fieldBound.end) {
          break;
        }
      }
      let beginRow = rowNum1 > rowNum2 ? rowNum2 : rowNum1;
      let endRow = rowNum1 < rowNum2 ? rowNum2 : rowNum1;
      let map = {};
      if (beginRow != endRow || field1 != field2) {
        for (let field of selectFieldArray) {
          for (let i = beginRow; i <= endRow; i++) {
            map[field.id + ":" + i] = true;
          }
        }
      }

      return {
        beginRow: beginRow,
        endRow: endRow,
        beginField: fieldBound.begin,
        endField: fieldBound.end,
        cellMap: map
      };
    },

    /**
     * 计算列宽
     * @param text
     * @returns {number}
     */
    judgeColumnWidth: function (text) {
      let array = text.split('');
      let length = 0;
      for (let char of array) {
        if (escape(char).indexOf("%u") < 0) {
          length++;
        } else {
          length += 2;
        }
      }
      return (length + 4) * 7;
    },
    /**
     * 查找某列合理的最长字符串
     * @param text
     * @returns {number}
     */
    judgeLongestColumnWidth: function (field, dataList) {
      let text = '默认字';
      if (field == undefined || dataList == undefined) {
        return text;
      }
      for (let item of dataList) {
        let data = item[field.id];
        if (data) {
          data = data + '';
        }
        if (data && data.startsWith('data:image')) {
          continue;
        }
        if (data) {
          data = data.trim();
        }
        if (data != undefined && data.length > text.length) {
          text = data;
        }
      }
      if (field.name && field.name.length > text.length) {
        text = field.name;
      }

      // if (text.length > text2.length * 2) {
      //   //如果排名第一的字符串长度超过第二的字符串长度3倍，则认为不合理
      //   text = text2;
      // }
      return this.judgeColumnWidth(text);
    },
    // 横向合并头部单元格
    headerCellStyleRender: function ({
                                       row,
                                       column,
                                       rowIndex,
                                       columnIndex
                                     }) {
      let result = {};
      if (this.borderColor) {
        result['border-color'] = this.borderColor;
      }

      return result;
    },

    //单元格样式
    cellStyleRender({
                      row,
                      column,
                      rowIndex,
                      columnIndex
                    },hook) {
      let result = {};
      if (this.borderColor) {
        result['border-color'] = this.borderColor;
      }

      if (hook) {
        let tmp = hook({row, column, rowIndex, columnIndex});
        if(tmp) {
          result = Object.assign(result,tmp);
        }
      }
      if(this.selectArea&&this.selectArea.cellMap&&this.selectArea.cellMap[column.property+':'+row.rowNum]) {
        //如果处于选中区域，则进行标注
        result['background-color'] = '#9ed0ff';
      } else if(this.changeCellMap[column.property+':'+row.rowNum]) {
        result['background-color'] = '#fdf6ec';
      }
      return result;

    },

    processInputValue: function (row, field, value) {
      if (field.dataType == 'number') {
        value = value.replace(/[^\d.]/g, '');
        row[field.id] = value;
      }
    },

    excelMergeMethod: function ({row, column, rowIndex, columnIndex}, rowOffset) {
      if (this.virtualMode && row.virtualRowNum) {
        //虚拟视图下dom复用导致rowIndex不准确
        rowIndex = row.virtualRowNum;
      }
      if (!this.mergeRange) {
        return;
      }
      let excelMergeRowIndex = rowIndex;
      if (rowOffset && rowOffset > 0) {
        //存在锁定表头时主体数据偏移定位
        excelMergeRowIndex = rowIndex + rowOffset;
      } else {
        rowOffset = 0;
      }
      let mergeData = this.mergeRange[excelMergeRowIndex + "_" + columnIndex];
      if (mergeData) {
        if (this.virtualMode && this.virtualDataRange
            && this.virtualDataRange.start == rowIndex
            && mergeData.rowspan == 0) {
          //如果是虚拟视图（行虚拟），若当前展示所有行有行合并且行合并开始行不在虚拟视图范围内，需要调整虚拟视图第一条为行合并开始
          let endIndex = rowIndex + 1;
          for (; endIndex < this.virtualDataRange.end; endIndex++) {
            let tmpMergeData = this.mergeRange[(endIndex + rowOffset) + "_" + columnIndex];
            if (!tmpMergeData || tmpMergeData.rowspan > 0) {
              break;
            }
          }

          //虚拟视图下需要将合并单元格数据转换到新的虚拟合并单元格
          let startIndex = rowIndex - 1;
          for (; startIndex >= 0; startIndex--) {
            let tmpMergeData = this.mergeRange[(startIndex + rowOffset) + "_" + columnIndex];
            if (tmpMergeData && tmpMergeData.rowspan > 0) {
              let value = this.dataList[startIndex][this.leafColumnList[columnIndex]];
              if (value) {
                this.dataList[rowIndex][this.leafColumnList[columnIndex]] = value;
              }
              break;
            }
          }

          // console.log('row:'+rowIndex+'col:'+columnIndex+',rowspan:'+(endIndex-rowIndex)+',colspan:'+mergeData.colspan)
          // console.log(row)
          // console.log(sheet)
          return {
            rowspan: endIndex - rowIndex,
            colspan: mergeData.colspan,
            // 'text-align': align
          };

        } else if (rowIndex == 0 && mergeData.rowspan == 0) {
          //解决行合并跨锁定表头问题
          let endIndex = rowIndex + 1;
          // for(;endIndex<this.bodyDataList.length;endIndex++) {
          for (; endIndex < this.dataList.length; endIndex++) {
            let tmpMergeData = this.mergeRange[(endIndex + rowOffset) + "_" + columnIndex];
            if (!tmpMergeData || tmpMergeData.rowspan > 0) {
              break;
            }
          }
          return {
            rowspan: endIndex - rowIndex,
            colspan: mergeData.colspan,
            // 'text-align': align
          };
        }
        // console.log('row:'+rowIndex+'col:'+columnIndex+',rowspan:'+mergeData.rowspan+',colspan:'+mergeData.colspan)
        // console.log(row)

        return {
          rowspan: mergeData.rowspan,
          colspan: mergeData.colspan,
          // 'text-align': align
        };
      }

    },
    /**
     * 记录虚拟视图下展示数据的开始与结束索引
     * @param start
     * @param end
     */
    updateVirtualDataRange({start, end}) {
      //记录当前表格虚拟展示数据范围
      this.virtualDataRange = {start: start, end: end};
    },
    //加载用户数据
    loadUserData: function (idList,hook) {
      if(!idList||idList.length<=0) {
        if(hook) {
          hook({});
        }
        return;
      }
      //过滤已经加载用户
      let idMap = [];
      for(let item of idList) {
        if(this.userMap[item]) {
          continue;
        }
        idMap[item]=true;
      }
      let idSet = [];
      for(let key in idMap) {
        idSet.push(key);
      }
      if(idSet.length<=0) {
        if(hook) {
          hook({});
        }
        return;
      }
      this.$post("/user/name_data", {pageSize:-1,filterIdSet:idSet},(response) => {
        let userMap = JSON.parse(JSON.stringify(this.userMap));
        for(let item of response.data) {
          userMap[item.id] = item;
        }
        for(let id of idSet) {
          if(!userMap[id]) {
            //用户信息不存在则新建对应数据，防止重复请求
            userMap[id] = {id:id,name:id};
          }
        }
        this.userMap = userMap;
        if(hook) {
          hook(userMap);
        }
      },()=>{

      });
    },
    //加载用户数据
    loadOfficeData: function (idList,hook) {
      if(!idList||idList.length<=0) {
        if(hook) {
          hook({});
        }
        return;
      }
      //过滤已经加载用户
      let idMap = [];
      for(let item of idList) {
        if(this.officeMap[item]) {
          continue;
        }
        idMap[item]=true;
      }
      let idSet = [];
      for(let key in idMap) {
        idSet.push(key);
      }
      if(idSet.length<=0) {
        if(hook) {
          hook({});
        }
        return;
      }
      this.$post("/company/name_data", {pageSize:-1,filterIdSet:idSet},(response) => {
        let officeMap = JSON.parse(JSON.stringify(this.officeMap));
        for(let item of response.data) {
          officeMap[item.id] = item;
        }
        for(let id of idSet) {
          if(!officeMap[id]) {
            //用户信息不存在则新建对应数据，防止重复请求
            officeMap[id] = {id:id,name:id};
          }
        }
        this.officeMap = officeMap;
        if(hook) {
          hook(officeMap);
        }
      },()=>{
        if(hook) {
          hook(idSet);
        }
      });
    },
    //加载数据列表
    loadNameDisplayMap(dataUrl,hook) {
      if(this.nameDisplayMap[dataUrl]) {
        if(hook) {
          hook(this.nameDisplayMap[dataUrl]);
        }
        return;
      }
      this.$get(dataUrl, {}, (response) => {
        if (!response.data) {
          hook();
          return;
        }
        let map = {};
        for (let item of response.data) {
          map[item.id] = item.name;
        }
        let totalMap = JSON.parse(JSON.stringify(this.nameDisplayMap));
        totalMap[dataUrl] = map;
        this.nameDisplayMap = totalMap;

        hook(map);
      }, () => {
      })
    },
    handleSelectChange(val) {
      this.$emit('selection-change',val)
    },
    //单元格数据变更监听
    handleCellChange(field,row) {
      this.changeCellMap[field.id+':'+row.rowNum] = true;
    },
    //获取变更数据
    getChangeData(){
      let list = [];
      let dataMap = {};
      for(let row of this.dataList) {
        dataMap[row.rowNum+''] = row;
      }
      for(let key in this.changeCellMap) {
        let tmpArray = key.split(':');
        if(tmpArray&&tmpArray.length==2) {
          let rowNum = tmpArray[1];
          let rowData = dataMap[rowNum+''];
          if(rowData) {
            list.push(JSON.parse(JSON.stringify(rowData)));
          }
        }
      }
      return list;
    },
    getDataList() {
      return this.dataList;
    },
    //更新表格显示
    updateTable() {
      this.timestamp = new Date().getTime();
    },
    //加载字段额外所需数据
    loadFieldExtraData(leafColumnList,dataList) {
      if(!dataList||dataList.length<=0) {
        return;
      }
      //记录数据加载标记
      let loadMetaTaskList = [];
      let loadDataUrlTaskList = [];
      let loadOfficeTaskList = [];
      let loadUserTaskList = [];


      //对列选择类数据进行加载
      for(let col of leafColumnList) {
        if ((col.type == 'meta' && col.source)
            ||(col.component&&(col.type=='meta'||col.component.id=='meta-select')&&col.component.type)) {
          loadMetaTaskList.push({type:'meta',field:col});
          if(!this.fieldDataNameMap[col.id]) {
            this.fieldDataNameMap[col.id] = {};
          }
        }
        if(col.type=='office') {
          loadOfficeTaskList.push({type:'office',field:col});
          if(!this.fieldDataNameMap[col.id]) {
            this.fieldDataNameMap[col.id] = {};
          }
        } else
        if(col.type=='user') {
          //处理用户类型列
          loadUserTaskList.push({type:'user',field:col});
          if(!this.fieldDataNameMap[col.id]) {
            this.fieldDataNameMap[col.id] = {};
          }
        } else if(col.type=='name-display'&&col.dataUrl) {
          loadDataUrlTaskList.push({type:'name-display',field:col});
          if(!this.fieldDataNameMap[col.id]) {
            this.fieldDataNameMap[col.id] = {};
          }
        }
      }

      if(!this.fieldDataNameMap['unit-type']) {
        this.fieldDataNameMap['unit-type'] = {};
      }
      if(loadOfficeTaskList.length>0) {
        let officeIdList = [];
        for (let item of dataList) {
          //记录用户id数据，用于加载用户数据
          for (let task of loadOfficeTaskList) {
            let officeId = item[task.field.id];
            if (officeId) {
              officeIdList.push(officeId)
            }
          }
        }
        if(!this.fieldDataInitMap['loading-office']) {
          this.fieldDataInitMap['loading-office'] = 'init';
          this.loadOfficeData(officeIdList, () => {
            this.fieldDataInitMap['loading-office'] = 'complete';
            let officeNameMap = {};
            for (let key in this.officeMap) {
              officeNameMap[key] = this.officeMap[key].name;
            }
            for (let item of loadOfficeTaskList) {
              this.fieldDataNameMap[item.field.id] = officeNameMap;
            }
            this.updateTable();
            delete this.fieldDataInitMap['loading-office'];
          })
        }
      }
      if (loadUserTaskList.length > 0) {
        let userIdList = [];
        for (let item of dataList) {
          //记录用户id数据，用于加载用户数据
          for (let task of loadUserTaskList) {
            let userId = item[task.field.id];
            if (userId) {
              userIdList.push(userId)
            }
          }
        }
        if (userIdList.length > 0) {
          if(!this.fieldDataInitMap['loading-user']) {
            this.fieldDataInitMap['loading-user'] = 'init';
            //加载数据列表中用到的用户数据
            this.loadUserData(userIdList, (map) => {
              this.fieldDataInitMap['loading-user'] = 'complete';
              let userNameMap = {};
              for(let key in this.userMap) {
                userNameMap[key] = this.userMap[key].name;
              }
              for (let item of loadUserTaskList) {
                this.fieldDataNameMap[item.field.id] = userNameMap;
              }
              this.updateTable();
              // this.fieldDataNameMap = JSON.parse(JSON.stringify(this.fieldDataNameMap));
              delete this.fieldDataInitMap['loading-user'];
            });
          }
        } else {
        }
      }
      let hasUnitType = false;
      for (let item of loadMetaTaskList) {
        const typeId = item.field.source;
        if(typeId == 'unit-type') {
          hasUnitType = true;
        }
        if(this.fieldDataInitMap[item.field.id]) {
          continue;
        }
        this.fieldDataInitMap[item.field.id] = 'init';
        this.loadMetaList(typeId, (list) => {
          let map = {};
          for(let item of list) {
            map[item.id] = item.name;
          }
          this.fieldDataInitMap[item.field.id] = 'complete';
          this.fieldDataNameMap[item.field.id] = map;
          this.fieldDataListMap[item.field.id] = list;
          this.updateTable();
          // this.fieldDataNameMap = JSON.parse(JSON.stringify(this.fieldDataNameMap));
          // this.fieldDataListMap = JSON.parse(JSON.stringify(this.fieldDataListMap));
        });
      }
      if(hasUnitType!=true&&!this.fieldDataNameMap['unit-type']) {
        this.loadMetaList('unit-type', (list) => {
          let map = {};
          for(let item of list) {
            map[item.id] = item.name;
          }
          this.fieldDataNameMap['unit-type'] = map;
          this.updateTable();
          // this.fieldDataNameMap = JSON.parse(JSON.stringify(this.fieldDataNameMap));
        });
      }
      for (let item of loadDataUrlTaskList) {
        if(this.fieldDataInitMap[item.field.id]) {
          continue;
        }
        this.fieldDataInitMap[item.field.id] = 'init';
        //名称展示列
        this.loadNameDisplayMap(item.field.dataUrl,(dataMap)=>{
          this.fieldDataInitMap[item.field.id] = 'complete';
          this.fieldDataNameMap[item.field.id] = dataMap;
          this.updateTable();
          // this.fieldDataNameMap = JSON.parse(JSON.stringify(this.fieldDataNameMap));
        });
      }

    },
    //将光标所处单元格数据向右填充
    fillCellDataToRight() {
      if(this.fillOption.beginField == null||this.fillOption.beginRow == null) {
        return;
      }

      if(!this.dataList||this.dataList.length<=this.fillOption.beginRow) {
        return;
      }
      let value = this.dataList[this.fillOption.beginRow][this.fillOption.beginField];
      let start = false;
      for (let field of this.columnList) {
        if (start == false&&field.id != this.fillOption.beginField) {
          continue;
        }
        start = true;
        this.dataList[this.fillOption.beginRow][field.id] = value;
        this.changeCellMap[field.id+':'+this.fillOption.beginRow] = true;
      }
    },

    //将光标所处单元格数据向下填充
    fillCellDataToBottom() {
      if(this.fillOption.beginField == null||this.fillOption.beginRow == null) {
        return;
      }


      for (let field of this.columnList) {
        if (field.id != this.fillOption.beginField) {
          continue;
        }
        if(!this.dataList||this.dataList.length<=this.fillOption.beginRow) {
          break;
        }
        let value = this.dataList[this.fillOption.beginRow][this.fillOption.beginField];
        for(let rowNum=this.fillOption.beginRow+1;rowNum<this.dataList.length;rowNum++) {
          this.dataList[rowNum][this.fillOption.beginField] = value;
          this.changeCellMap[this.fillOption.beginField+':'+rowNum] = true;
        }
      }
    },
  }
}
</script>